package mainWindow;
import ftp.FTPConnection;
import interfaceComponents.TestHolder;
import interfaceComponents.TestSelector;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;

import questionTypes.Question;
import utilities.Colors;
import utilities.Constants;
import utilities.StudentConverters;

public class MainStudentWindow extends JPanel{
	private static final long serialVersionUID = 4547592892218285620L;
	private JFrame frame;
	private String username;
	private FTPConnection ftpClient;
	private TreePath currentTestPath;
	private MenuBar menuBar;
	private String[] name;
	private TestHolder holder;
	private TestSelector selector;
	private boolean inAssignment;

	public MainStudentWindow(String user, FTPConnection ftpConnetion) {
		username = user;
		ftpClient = ftpConnetion;
		init();
	}

	public JFrame getFrame() {
		return frame;
	}

	public void selectTest(TreePath path, boolean takenBefore)
			throws IOException {
		System.out.println("Method selected");
		currentTestPath = path;
		Object[] splitPath = currentTestPath.getPath();
		String className = splitPath[1].toString().substring(
				splitPath[1].toString().indexOf(" "));
		String assingmentName = splitPath[2].toString();
		selector.setPathLabel(className + " | " + assingmentName);
		importTest(currentTestPath);
		if (takenBefore) {
			importSubmission();
			gradeTest();
			inAssignment = false;
		} else {
			inAssignment = true;
		}

	};

	public void submitTest() throws IOException {
		setCursor (Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
		File output = new File("output.txt");
		output.createNewFile();
		PrintWriter pw = new PrintWriter(output);
		boolean problem = false;
		System.out.println("Array Size: " + holder.getSelector().getQuestions().size());
		for (Question question : holder.getSelector().getQuestions()) {
			if (question.getAnswerChoice() == -1 && !problem) {
				JOptionPane.showMessageDialog(frame, "Please select an answer for Question "+ question.getQuestionNumber());
				problem = true;
			}
			pw.println(question.getQuestionNumber() + " "
					+ question.getAnswerChoice());
			System.out.println(question.getQuestionNumber() + " "
					+ question.getAnswerChoice());
		}
		pw.close();
		if (!problem) {
			ftpClient.uploadFile(StudentConverters.createSubmissionPath(
					currentTestPath, username), new FileInputStream(output));
			gradeTest();
		}
		setCursor (Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
	}

	private void init() {
		frame = new JFrame();
		ImageIcon icon = new ImageIcon("logo.png");
		frame.setIconImage(icon.getImage());
		frame.setMinimumSize(new Dimension(1200, 680));
		frame.setResizable(true);
		frame.setVisible(true);
		frame.setExtendedState(frame.getExtendedState() | JFrame.MAXIMIZED_BOTH);
		frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		name = ftpClient.getDataHolder().getName(username);
		frame.setTitle(name[0] + "'s Console");
		frame.getContentPane().setLayout(new BorderLayout());

		final int gap = 10;
		frame.getContentPane().add(this, BorderLayout.CENTER);
		frame.getContentPane().add(Box.createVerticalStrut(gap),
				BorderLayout.NORTH);
		frame.getContentPane().add(Box.createVerticalStrut(gap),
				BorderLayout.SOUTH);
		frame.getContentPane().add(Box.createHorizontalStrut(gap),
				BorderLayout.EAST);
		frame.getContentPane().add(Box.createHorizontalStrut(gap),
				BorderLayout.WEST);

		setLayout(new BorderLayout());
		setBackground(Colors.TRANSPARENT);

		menuBar = new MenuBar();
		frame.setJMenuBar(menuBar.getBar());

		frame.setBackground(Colors.FRAME_BACKGROUND);
		frame.getContentPane().setBackground(Colors.TRANSPARENT);

		selector = new TestSelector(ftpClient, username);
		selector.setBackground(Colors.TRANSPARENT);
		add(selector, BorderLayout.WEST);
		addTreeSelectionListener(selector.getTree());

		frame.addWindowListener(new java.awt.event.WindowAdapter() {
			@Override
			public void windowClosing(java.awt.event.WindowEvent windowEvent) {
				if(inAssignment){
					JOptionPane.showMessageDialog(frame, "You mush finish and submit the assignment before closing the program.");
				}else if (JOptionPane
						.showConfirmDialog(frame,
								"Are you sure you want to exit the program?", "Confirm Exit",
								JOptionPane.YES_NO_OPTION,
								JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
					System.exit(0);
				}
			}
		});
	}

	public void addTreeSelectionListener(JTree treeIn) {
		treeIn.getSelectionModel().addTreeSelectionListener(
				new TreeSelectionListener() {
					@Override
					public void valueChanged(TreeSelectionEvent e) {
						if (selector.isTest(e.getNewLeadSelectionPath())) {
							// If student has already taken test
							if (inAssignment) {
								JOptionPane.showMessageDialog(frame,
												"You must finish and submit the current assingment before switching assingments.");
							} else {
								if (ftpClient.getMap().get(
										StudentConverters.treePathToMap(e
												.getNewLeadSelectionPath(), username))) {
									try {
										selectTest(e.getNewLeadSelectionPath(),
												true);
									} catch (IOException e1) {
										e1.printStackTrace();
									}
								} else {

									if (JOptionPane
											.showConfirmDialog(
													frame,
													"Are you sure you want to begin this assingment?",
													"Confirm",
													JOptionPane.YES_NO_OPTION,
													JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
										try {
											selectTest(
													e.getNewLeadSelectionPath(),
													false);
										} catch (IOException e1) {
											e1.printStackTrace();
										}
									}
								}
							}
						}

						// Don't really have any reason for these to be here
						// Am leaving in just in case
						if (selector.isClass(e.getNewLeadSelectionPath())) {

						}
						if (selector.isRoot(e.getNewLeadSelectionPath())) {

						}
					}
				});
	}

	public void gradeTest() {
		try {
			importKey();
		} catch (IOException e) {
			e.printStackTrace();
		}
		double numberOfQuestions = holder.getSelector().getQuestions().size();
		double correctAnswers = 0;
		for (Question question : holder.getSelector().getQuestions()) {
			question.setEditable(false, false);
			if (question.isCorrect()) {
				correctAnswers++;
			}
		}
		double grade = correctAnswers * 100.0f / numberOfQuestions;
		String text = (int) correctAnswers + "/" + (int) numberOfQuestions
				+ " | " + (int) grade + "%";
		// frame.setTitle(text);
		menuBar.setWhiteSpaceText("      Grade: " + text);
		menuBar.stopAllowingSubmissions();
		if(inAssignment){
			try {
				selector.refreshStudentTree();
			} catch (IOException e) {
				e.printStackTrace();
			}
			addTreeSelectionListener(selector.getTree());
			frame.revalidate();
		}
		inAssignment = false;
	}

	public void importKey() throws IOException {
		File file = new File("key.key");
		file.createNewFile();
		ftpClient.getFile(StudentConverters.keyPathToKey(currentTestPath, username),
				"key.key");
		Scanner scanner = new Scanner(file);
		while (scanner.hasNext()) {
			String string = scanner.nextLine();
			String[] splitString = string.split(" ");

			try {
				holder.getSelector().getQuestions()
						.get(Integer.parseInt(splitString[0]))
						.setCorrectAnswer(Integer.parseInt(splitString[1]), true);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		scanner.close();
		frame.revalidate();
		file.delete();
	}

	public void importSubmission() throws IOException {
		File file = new File("key.key");
		file.createNewFile();
		ftpClient.getFile(StudentConverters.createSubmissionPath(
				currentTestPath, username), "key.key");
		Scanner scanner = new Scanner(file);
		while (scanner.hasNext()) {
			String string = scanner.nextLine();
			String[] splitString = string.split(" ");

			try {
				holder.getSelector().getQuestions()
						.get(Integer.parseInt(splitString[0]) - 1)
						.setSelected(Integer.parseInt(splitString[1]));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		scanner.close();
		frame.revalidate();
		file.delete();
	}

	public void importTest(TreePath testPath) throws IOException {
		if(holder == null){
			holder = new TestHolder(new MainWindow(username, ftpClient, false));
			add(holder, BorderLayout.CENTER);
		}
		
		holder.importTest(testPath, ftpClient, username);
		menuBar.startAllowingSubmissions();
	}

	class MenuBar {
		private JMenuBar jMenuBar;
		private JMenuItem submit;
		private JLabel gradeLabel;
		private JLabel connectionStatus;

		MenuBar() {
			this.start();
		}

		public void start() {
			jMenuBar = new JMenuBar();
			jMenuBar.setBackground(Colors.majorBarBackground);
			jMenuBar.setBorder(BorderFactory.createEmptyBorder());
			jMenuBar.setPreferredSize(new Dimension(100, 50));
			JMenu file = new JMenu(" File ");
			file.setBackground(null);
			file.setForeground(Colors.BAR_TEXT_COLOR);
			file.setFont(Fonts.jMenuBarFont);
			this.jMenuBar.add(file);
			
			JMenuItem logOut = new JMenuItem("Log Out");
			logOut.setFont(Fonts.jMenuBarFont);
			file.add(logOut);
			logOut.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					frame.setVisible(false);
					LoginFrame loginFrame = new LoginFrame("Login Screen");
					loginFrame.setVisible(true);
					loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
					loginFrame.setLocationRelativeTo(null);
					loginFrame.setResizable(false);
				}
			});

			JMenuItem exit = new JMenuItem("Exit");
			file.add(exit);
			exit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E,
					KeyEvent.CTRL_MASK));
			exit.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent arg0) {
					System.exit(0);
				}
			});

			JMenu view = new JMenu(" View ");
			jMenuBar.add(view);
			view.setBackground(null);
			view.setForeground(Colors.BAR_TEXT_COLOR);
			view.setFont(Fonts.jMenuBarFont);
			JMenu setTextSize = new JMenu("Set Text Size");
			view.add(setTextSize);

			for (int i = 8; i <= 46; i += 2) {
				JMenuItem setSize = new JMenuItem(i + "");
				setTextSize.add(setSize);
				final int temp = i;
				setSize.addActionListener(new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent arg0) {
						for (Question question : holder.getSelector()
								.getQuestions())
							question.setTextSize(temp);
					}
				});
			}

			final JCheckBoxMenuItem set = new JCheckBoxMenuItem(
					"Show Test Selector");
			set.setSelected(true);
			set.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent arg0) {
					selector.setVisible(set.isSelected());

				}
			});

			view.add(set);

			submit = new JMenuItem("Submit");
			jMenuBar.add(submit);
			submit.setVisible(false);
			submit.setBackground(null);
			submit.setForeground(Colors.BAR_TEXT_COLOR);
			submit.setEnabled(false);
			submit.setFont(Fonts.jMenuBarFont);
			submit.setMaximumSize(new Dimension(95, Constants.JMenuBarHeight));
			submit.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent arg0) {
					if(JOptionPane.showConfirmDialog(frame, "Are you sure you want to submit this assignment? This action cannot be undone.")==JOptionPane.OK_OPTION){
						try {
							submitTest();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
			});

			gradeLabel = new JLabel();
			jMenuBar.add(gradeLabel);
			gradeLabel.setFont(Fonts.jMenuBarFont);
			gradeLabel.setForeground(Colors.BAR_TEXT_COLOR);
			gradeLabel.setBackground(Colors.majorBarBackground);
			jMenuBar.add(Box.createGlue());

			connectionStatus = new JLabel(" Connected ");
			connectionStatus.setForeground(Colors.GOOD_CONNECTION);
			connectionStatus.setBackground(Colors.majorBarBackground);
			connectionStatus.setFont(Fonts.jMenuBarFont);
			jMenuBar.add(connectionStatus);

			ActionListener listener = new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					updateConnectionStatus();
				}
			};
			Timer timer = new Timer(5000, listener);
			timer.setDelay(5000);
			timer.start();

			JLabel username = new JLabel(" " + name[0] + " " + name[1] + " ");
			username.setBackground(null);
			username.setForeground(Colors.BAR_TEXT_COLOR);
			username.setFont(Fonts.jMenuBarFont);
			jMenuBar.add(username);

		}

		public void updateConnectionStatus(){
			System.out.println("Checking if connected");
			if(ftpClient.isConnected()){
				connectionStatus.setText(" Connected ");
				System.out.println("Connected");
				connectionStatus.setForeground(Colors.GOOD_CONNECTION);
				frame.revalidate();
			}else if(ftpClient.connectToServer()){
				connectionStatus.setText(" Connected ");
				System.out.println("Connected when updated");
				connectionStatus.setForeground(Colors.GOOD_CONNECTION);
				frame.revalidate();
			}else{
				connectionStatus.setText(" Not Connected ");
				connectionStatus.setForeground(Colors.BAD_CONNECTION);
				frame.revalidate();
			}
		}

		public JMenuBar getBar() {
			return jMenuBar;
		}

		public void startAllowingSubmissions() {
			submit.setEnabled(true);
			submit.setVisible(true);
		}

		public void stopAllowingSubmissions() {
			submit.setEnabled(false);
			submit.setVisible(false);
		}

		public void setWhiteSpaceText(String text) {
			gradeLabel.setText(text);
		}
	}

	public void setTimer(int time) {
		
	}
}